#pragma once

#include "Channel.h"
#include "Poller.h"
#include "noncopyable.h"
#include "Timestamp.h"
#include "CurrentThread.h"

#include <functional>
#include <vector>
#include <atomic>
#include <unistd.h>
#include <memory>
#include <mutex>

//一个线程对应一个EventLoop，一个EventLoop又包含多个Poller和Channel,也就是说一个线程可以监听多个事件
//事件循环类 主要包含了两个大模块 Channel Poller(epoll的抽象)
//相当于Reactor

//每个subReactor都监听了一个wakeup Channel，用于实现mainReactor和subReactor直接的交流
//即方便mainReactor唤醒subReactor

/**
* 减少编译依赖：前置声明可以减少头文件间的相互依赖，从而减少编译时间，特别是在大型项目中。
*避免循环依赖：在相互引用的类中，前置声明可以帮助避免循环依赖的问题。
*限制:

*只能用于指针和引用的声明：如果只是声明类的指针或引用，那么前置声明就足够了。
*不能用于成员函数的定义、成员变量的声明、或者需要知道类大小的任何场合。
*/
class Channel;
class Poller;
class EventLoop : noncopyable
{
public:
    using Functor = std::function<void()>;

    EventLoop();
    ~EventLoop();

    void loop(); //开启事件循环
    void quit(); //退出事件循环

    Timestamp pollReturnTime() const { return pollReturnTime_; }

    void runInLoop(Functor cb); //在当前loop中执行cb
    void queueInLoop(Functor cb); //把cb放入队列中，唤醒loop所在线程，执行cb

    void wakeup(); //唤醒subloop(subReactor)

    //EventLoop的方法=>Poller的方法
    void updateChannel(Channel* channel);
    void removeChannel(Channel* channel);
    bool hasChannel(Channel* channel);

    //判断EventLoop对象是否在自己的线程里面
    bool isInLoopThread() const { return threadId_ == CurrentThread::tid(); }

private:
    void handleRead(); //wake up
    void doPendingFunctors(); //执行回调

    using ChannelList = std::vector<Channel*>;

    std::atomic_bool looping_; //原子操作，通过CAS实现
    std::atomic_bool quit_; //标识退出loop循环
    
    const pid_t threadId_; //记录当前loop所在线程id
    
    Timestamp pollReturnTime_; //poller返回发生事件的channels的时间点
    std::unique_ptr<Poller> poller_; 

    //主要作用，当mainloop(mainReactor)获取一个新用户的channel,
    //通过轮询算法选择一个subloop(subReactor),通过该成员唤醒subloop处理channel
    int wakeupFd_; 
    std::unique_ptr<Channel> wakeupChannel_; //包含了wakeupFd_和感兴趣的事件
    
    ChannelList activeChannels_;

    std::atomic_bool callingPendingFunctors_; //标识当前loop是否有需要执行的回调操作
    std::vector<Functor> pendingFunctors_; //存储loop需要执行的所有的回调操作
    std::mutex mutex_; //互斥锁用来保护上面vector容器的线程安全操作
};